namespace ModelExamples {

  public ref class Emulator
  {
    ToolkitWorld::IWorldControl* pWorld;
    IModelScene* pScene;
    IModel* pShip;

    double _startTimeInSecond;
    double _curTimeInSecond;
    double _initialZ;
    double _initialTrim;
    double _initialTa;
    double _initialTf;
    double _depth;
  private:
    EResult SetTelegraphOrder(double dblOrder);
    double GetTelegraphOrder(bool returnState);
    double CalcDraft(bool isBow);
    double CalcPitch();

  public:
    Emulator(System::String^ strCabPath);

    void Start(double dblStartTimeInSecond);
    void Run(double dblCurrentTimeInSecond);

    //Order in %  [0%..100%]
    property double EngineOrder
    { 
      double get()
      {
        return GetTelegraphOrder(false);
      }
      void set(double order)
      {
        SetTelegraphOrder(order);
      }
    }    

    property double EngineOrderState
    { 
      double get()
      {
        return GetTelegraphOrder(true);
      }
    }    

    //Veocity in knots
    property double Velocity
    { 
      double get()
      {
        ModelState state;
        pShip->GetState(state);
        return state.mpsVx * 0.514;
      }
    }    

    //Sinkage in meters
    property double Sinkage
    { 
      double get()
      {
        ModelState state;
        pShip->GetState(state); 
        return _initialZ - state.mZg;
      }
    }    

    //Bow Sinkage in meters
    property double BowSinkage
    { 
      double get(){ return CalcDraft(true) - _initialTf;      }
    }    

    //Stern Sinkage in meters
    property double SternSinkage
    { 
      double get(){ return CalcDraft(false) - _initialTa;      }
    }    

    //Bow Draft in meters
    property double BowDraft
    { 
      double get(){ return CalcDraft(true);      }
    }    

    //Stern Draft in meters
    property double SternDraft
    { 
      double get(){ return CalcDraft(false);      }
    }    

    //Pitch in deg
    property double Pitch
    { 
      double get(){ return CalcPitch();      }
    }    

    //Depth in meters
    property double Depth
    { 
      double get()
      {
        return _depth;
      }
      void set(double depth)
      {
        _depth = depth;
        pWorld->SetUniformDepth(_depth);
      }
    }    

    //Maneuver time in seconds
    property double ManeuverTime
    { 
      double get()
      {
        return _curTimeInSecond - _startTimeInSecond;
      }
    }    

    property bool IsGrounded
    { 
      bool get()
      {
        IomComponentPtr pRoot;
        IomComponentPtr pState;
        pShip->GetIomModel(&pRoot);
        pRoot->get_Component(cidState, &pState);

        CDataValue val;
        pState->get_Value(pidObjectState, &val);
        long state = val;
        return state != OBJECT_STATE_RUNNING;
      }
    }    

    //ship.cidState.pidObjectState
  };  
}